import { useRouter } from "next/router";
import { GenerationLatencyChart } from "@/src/features/dashboard/components/LatencyChart";
import { ChartScores } from "@/src/features/dashboard/components/ChartScores";
import { TracesBarListChart } from "@/src/features/dashboard/components/TracesBarListChart";
import { ModelCostTable } from "@/src/features/dashboard/components/ModelCostTable";
import { ScoresTable } from "@/src/features/dashboard/components/ScoresTable";
import { ModelUsageChart } from "@/src/features/dashboard/components/ModelUsageChart";
import { TracesAndObservationsTimeSeriesChart } from "@/src/features/dashboard/components/TracesTimeSeriesChart";
import { UserChart } from "@/src/features/dashboard/components/UserChart";
import { TimeRangePicker } from "@/src/components/date-picker";
import { api } from "@/src/utils/api";
import { FeedbackButtonWrapper } from "@/src/features/feedback/component/FeedbackButton";
import { BarChart2 } from "lucide-react";
import { Button } from "@/src/components/ui/button";
import { PopoverFilterBuilder } from "@/src/features/filters/components/filter-builder";
import { type FilterState } from "@langfuse/shared";
import { type ColumnDefinition } from "@langfuse/shared";
import { useQueryFilterState } from "@/src/features/filters/hooks/useFilterState";
import { LatencyTables } from "@/src/features/dashboard/components/LatencyTables";
import { useMemo } from "react";
import {
findClosestDashboardInterval,
DASHBOARD_AGGREGATION_OPTIONS,
toAbsoluteTimeRange,
type DashboardDateRangeAggregationOption,
} from "@/src/utils/date-range-utils";
import { useDashboardDateRange } from "@/src/hooks/useDashboardDateRange";
import { useDebounce } from "@/src/hooks/useDebounce";
import { ScoreAnalytics } from "@/src/features/dashboard/components/score-analytics/ScoreAnalytics";
import SetupTracingButton from "@/src/features/setup/components/SetupTracingButton";
import { useUiCustomization } from "@/src/ee/features/ui-customization/useUiCustomization";
import { useEntitlementLimit } from "@/src/features/entitlements/hooks";
import Page from "@/src/components/layouts/page";
import { MultiSelect } from "@/src/features/filters/components/multi-select";
import {
convertSelectedEnvironmentsToFilter,
useEnvironmentFilter,
} from "@/src/hooks/use-environment-filter";
export default function Dashboard() {
const router = useRouter();
const projectId = router.query.projectId as string;
const { timeRange, setTimeRange } = useDashboardDateRange();
const absoluteTimeRange = useMemo(
() => toAbsoluteTimeRange(timeRange),
[timeRange],
);
const uiCustomization = useUiCustomization();
const lookbackLimit = useEntitlementLimit("data-access-days");
const [userFilterState, setUserFilterState] = useQueryFilterState(
[],
"dashboard",
projectId,
);
const traceFilterOptions = api.traces.filterOptions.useQuery(
{
projectId,
},
{
trpc: {
context: {
skipBatch: true,
},
},
refetchOnMount: false,
refetchOnWindowFocus: false,
refetchOnReconnect: false,
staleTime: Infinity,
},
);
const environmentFilterOptions =
api.projects.environmentFilterOptions.useQuery(
{
projectId,
fromTimestamp: absoluteTimeRange?.from,
},
{
trpc: {
context: {
skipBatch: true,
},
},
refetchOnMount: false,
refetchOnWindowFocus: false,
refetchOnReconnect: false,
staleTime: Infinity,
},
);
const environmentOptions: string[] =
environmentFilterOptions.data?.map((value) => value.environment) || [];
// Add effect to update filter state when environments change
const { selectedEnvironments, setSelectedEnvironments } =
useEnvironmentFilter(environmentOptions, projectId);
const nameOptions = traceFilterOptions.data?.name || [];
const tagsOptions = traceFilterOptions.data?.tags || [];
const filterColumns: ColumnDefinition[] = [
{
name: "Trace Name",
id: "traceName",
type: "stringOptions",
options: nameOptions,
internal: "internalValue",
},
{
name: "Tags",
id: "tags",
type: "arrayOptions",
options: tagsOptions,
internal: "internalValue",
},
{
name: "User",
id: "user",
type: "string",
internal: "internalValue",
},
{
name: "Release",
id: "release",
type: "string",
internal: "internalValue",
},
{
name: "Version",
id: "version",
type: "string",
internal: "internalValue",
},
];
const dashboardTimeRangePresets = DASHBOARD_AGGREGATION_OPTIONS;
const agg = useMemo(() => {
if ("range" in timeRange) {
return timeRange.range as DashboardDateRangeAggregationOption;
}
return findClosestDashboardInterval(timeRange) ?? "last7Days";
}, [timeRange]);
const fromTimestamp = absoluteTimeRange?.from
? absoluteTimeRange.from
: new Date(new Date().getTime() - 1000);
const toTimestamp = absoluteTimeRange?.to ? absoluteTimeRange.to : new Date();
const timeFilter = [
{
type: "datetime" as const,
column: "startTime",
operator: ">" as const,
value: fromTimestamp,
},
{
type: "datetime" as const,
column: "startTime",
operator: "<" as const,
value: toTimestamp,
},
];
const environmentFilter = convertSelectedEnvironmentsToFilter(
["environment"],
selectedEnvironments,
);
const mergedFilterState: FilterState = [
...userFilterState,
...timeFilter,
...environmentFilter,
];
return (